/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _DAL_CYCLONEDDS_TOPIC_SERTYPE_MANAGER_HPP_
#define _DAL_CYCLONEDDS_TOPIC_SERTYPE_MANAGER_HPP_

#include <mutex>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include "dds/dds.h"

class TopicSertypeManager
{
protected:
    TopicSertypeManager();
    static TopicSertypeManager* singleton_;

public:
    TopicSertypeManager(TopicSertypeManager& other) = delete;
    void operator=(const TopicSertypeManager&) = delete;
    static TopicSertypeManager* GetInstance();

    // sertype CRUD
    void AddTopicSerType(const dds_entity_t& participant,
                         const std::string& type_name,
                         struct sertype_dal* sertype);
    void RemoveTopicSerType(const dds_entity_t& participant, const std::string& type_name);
    void RemoveTopicSerTypeByTypeName(const std::string& type_name);
    struct sertype_dal* GetTopicSerType(const dds_entity_t& participant,
                                        const std::string& type_name);
    void RemoveParticipant(const dds_entity_t& participant);

    // topic_name CRUD
    void AddTopicName(const dds_entity_t& participant, const std::string& topic_name);
    bool IsTopicNameExist(const dds_entity_t& participant, const std::string& topic_name);
    void RemoveTopicName(const dds_entity_t& participant, const std::string& topic_name);

    //
    void AddTopicInfo(const dds_entity_t& topic,
                      const std::string& topic_name,
                      const std::string& type_name);
    void DeleteTopicInfo(const dds_entity_t& topic);
    std::string GetTopicName(const dds_entity_t& topic);
    std::string GetTypeName(const dds_entity_t& topic);

    // undeleted topic
    void AddEntityToParticipant(const dds_entity_t& participant, const dds_entity_t& entity);
    void RemoveEntityFromParticipant(const dds_entity_t& participant, const dds_entity_t& entity);
    bool IsParticipantEntity(const dds_entity_t& participant, const dds_entity_t& entity);
    bool IsParticipantNoEntity(const dds_entity_t& participant);

private:
    // key: participant, value: <key: type_name, value: sertype>
    std::unordered_map<dds_entity_t, std::unordered_map<std::string, struct sertype_dal*>>
        sertype_map_;

    // key: participant, value: topic_name
    std::unordered_map<dds_entity_t, std::unordered_set<std::string>> topic_map_;

    // key: topic, value: <key: topic_name, value: type_name>
    std::unordered_map<dds_entity_t, std::tuple<std::string, std::string>> topic_info_map_;

    // key: participant, value: set<entity(pub/sub/topic)>
    std::unordered_map<dds_entity_t, std::unordered_set<dds_entity_t>> participant_entities_map_;

    std::mutex mutex_;
};

#endif  // _DAL_CYCLONEDDS_TOPIC_SERTYPE_MANAGER_HPP_